/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controllers;

import Controllers.exceptions.IllegalOrphanException;
import Controllers.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entities.Owner;
import Entities.Pet;
import Entities.Record;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author Heinz Hernandez
 */
public class PetJpaController implements Serializable {

    public PetJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Pet pet) throws IllegalOrphanException {
        if (pet.getRecordList() == null) {
            pet.setRecordList(new ArrayList<Record>());
        }
        List<String> illegalOrphanMessages = null;
        Record recIdOrphanCheck = pet.getRecId();
        if (recIdOrphanCheck != null) {
            Pet oldPetIdOfRecId = recIdOrphanCheck.getPetId();
            if (oldPetIdOfRecId != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("The Record " + recIdOrphanCheck + " already has an item of type Pet whose recId column cannot be null. Please make another selection for the recId field.");
            }
        }
        if (illegalOrphanMessages != null) {
            throw new IllegalOrphanException(illegalOrphanMessages);
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Owner ownId = pet.getOwnId();
            if (ownId != null) {
                ownId = em.getReference(ownId.getClass(), ownId.getOwnId());
                pet.setOwnId(ownId);
            }
            Record recId = pet.getRecId();
            if (recId != null) {
                recId = em.getReference(recId.getClass(), recId.getRecId());
                pet.setRecId(recId);
            }
            List<Record> attachedRecordList = new ArrayList<Record>();
            for (Record recordListRecordToAttach : pet.getRecordList()) {
                recordListRecordToAttach = em.getReference(recordListRecordToAttach.getClass(), recordListRecordToAttach.getRecId());
                attachedRecordList.add(recordListRecordToAttach);
            }
            pet.setRecordList(attachedRecordList);
            em.persist(pet);
            if (ownId != null) {
                ownId.getPetList().add(pet);
                ownId = em.merge(ownId);
            }
            if (recId != null) {
                recId.setPetId(pet);
                recId = em.merge(recId);
            }
            for (Record recordListRecord : pet.getRecordList()) {
                Pet oldPetIdOfRecordListRecord = recordListRecord.getPetId();
                recordListRecord.setPetId(pet);
                recordListRecord = em.merge(recordListRecord);
                if (oldPetIdOfRecordListRecord != null) {
                    oldPetIdOfRecordListRecord.getRecordList().remove(recordListRecord);
                    oldPetIdOfRecordListRecord = em.merge(oldPetIdOfRecordListRecord);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Pet pet) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Pet persistentPet = em.find(Pet.class, pet.getPetId());
            Owner ownIdOld = persistentPet.getOwnId();
            Owner ownIdNew = pet.getOwnId();
            Record recIdOld = persistentPet.getRecId();
            Record recIdNew = pet.getRecId();
            List<Record> recordListOld = persistentPet.getRecordList();
            List<Record> recordListNew = pet.getRecordList();
            List<String> illegalOrphanMessages = null;
            if (recIdNew != null && !recIdNew.equals(recIdOld)) {
                Pet oldPetIdOfRecId = recIdNew.getPetId();
                if (oldPetIdOfRecId != null) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("The Record " + recIdNew + " already has an item of type Pet whose recId column cannot be null. Please make another selection for the recId field.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (ownIdNew != null) {
                ownIdNew = em.getReference(ownIdNew.getClass(), ownIdNew.getOwnId());
                pet.setOwnId(ownIdNew);
            }
            if (recIdNew != null) {
                recIdNew = em.getReference(recIdNew.getClass(), recIdNew.getRecId());
                pet.setRecId(recIdNew);
            }
            List<Record> attachedRecordListNew = new ArrayList<Record>();
            for (Record recordListNewRecordToAttach : recordListNew) {
                recordListNewRecordToAttach = em.getReference(recordListNewRecordToAttach.getClass(), recordListNewRecordToAttach.getRecId());
                attachedRecordListNew.add(recordListNewRecordToAttach);
            }
            recordListNew = attachedRecordListNew;
            pet.setRecordList(recordListNew);
            pet = em.merge(pet);
            if (ownIdOld != null && !ownIdOld.equals(ownIdNew)) {
                ownIdOld.getPetList().remove(pet);
                ownIdOld = em.merge(ownIdOld);
            }
            if (ownIdNew != null && !ownIdNew.equals(ownIdOld)) {
                ownIdNew.getPetList().add(pet);
                ownIdNew = em.merge(ownIdNew);
            }
            if (recIdOld != null && !recIdOld.equals(recIdNew)) {
                recIdOld.setPetId(null);
                recIdOld = em.merge(recIdOld);
            }
            if (recIdNew != null && !recIdNew.equals(recIdOld)) {
                recIdNew.setPetId(pet);
                recIdNew = em.merge(recIdNew);
            }
            for (Record recordListOldRecord : recordListOld) {
                if (!recordListNew.contains(recordListOldRecord)) {
                    recordListOldRecord.setPetId(null);
                    recordListOldRecord = em.merge(recordListOldRecord);
                }
            }
            for (Record recordListNewRecord : recordListNew) {
                if (!recordListOld.contains(recordListNewRecord)) {
                    Pet oldPetIdOfRecordListNewRecord = recordListNewRecord.getPetId();
                    recordListNewRecord.setPetId(pet);
                    recordListNewRecord = em.merge(recordListNewRecord);
                    if (oldPetIdOfRecordListNewRecord != null && !oldPetIdOfRecordListNewRecord.equals(pet)) {
                        oldPetIdOfRecordListNewRecord.getRecordList().remove(recordListNewRecord);
                        oldPetIdOfRecordListNewRecord = em.merge(oldPetIdOfRecordListNewRecord);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = pet.getPetId();
                if (findPet(id) == null) {
                    throw new NonexistentEntityException("The pet with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Pet pet;
            try {
                pet = em.getReference(Pet.class, id);
                pet.getPetId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The pet with id " + id + " no longer exists.", enfe);
            }
            Owner ownId = pet.getOwnId();
            if (ownId != null) {
                ownId.getPetList().remove(pet);
                ownId = em.merge(ownId);
            }
            Record recId = pet.getRecId();
            if (recId != null) {
                recId.setPetId(null);
                recId = em.merge(recId);
            }
            List<Record> recordList = pet.getRecordList();
            for (Record recordListRecord : recordList) {
                recordListRecord.setPetId(null);
                recordListRecord = em.merge(recordListRecord);
            }
            em.remove(pet);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Pet> findPetEntities() {
        return findPetEntities(true, -1, -1);
    }

    public List<Pet> findPetEntities(int maxResults, int firstResult) {
        return findPetEntities(false, maxResults, firstResult);
    }

    private List<Pet> findPetEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Pet.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Pet findPet(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Pet.class, id);
        } finally {
            em.close();
        }
    }

    public int getPetCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Pet> rt = cq.from(Pet.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
